



import React, { FC , memo, useEffect } from 'react'

// 练习 TS 
// https://www.cnblogs.com/samve/p/12347658.html
// typescript 不过是 javascript 严格的语法模式  
// 所有的变量声明来源和类型 
// Typescript原始数据类型：
// string
// number      
// boolean      
// null
// undefined 
// enum   枚举类型 
// symbol    
// 空值一般采用 void 表示，void可以表示变量，也可以表示函数返回值。
// any 任意类型
// Array 数组  []  array
// Object 对象  {}  object 


// 1.FC  React.FC是函数式组件，是在TypeScript使用的一个泛型，FC就是FunctionComponent的缩写，事实上React.FC可以写成React.FunctionComponent 
// 2.React.FC 包含了 PropsWithChildren 的泛型，不用显式的声明 props.children 的类型。React.FC<> 对于返回类型是显式的，而普通函数版本是隐式的（否则需要附加注释
// 3.React.FC提供了类型检查和自动完成的静态属性：displayName，propTypes和defaultProps（注意：defaultProps与React.FC结合使用会存在一些问题）。
// 4.我们使用React.FC来写 React 组件的时候，是不能用setState的，取而代之的是useState()、useEffect等 Hook API



const Demo:FC = memo(() => {

    useEffect(()=>{

    },[])


    let a ;    // 任意类型
    let b = 100;
    let c:number = 999
    let d:number | string = 'Hello'
    let e:boolean = true;
    
    let h1:any = []
    let h2:symbol | string = '123'
    let obj:object = {}
    let list:Array<string> = ['1','2']
    let list2:Array<number> = [1,23,3,4]
    let list3:Array<object> = [{},{},{}]

    let arr: string[] = ['1','2']
    let arr2: any[] = [1,2,3,4,"5"]


    // Typescript中对象类型-接口：  interface 
    // 可描述类的一部分抽象行为，也可描述对象的结构形状。

    interface Istate1 {
        name: string;
        age: number;
    }

    const obj1: Istate1 = {
        name: "Tom",
        age: 20,
    }

    // 可选属性  ? 
    interface Istate2 {
        name: string;
        age?: number;
    }
    const obj2: Istate2 = {
        name: "张三",
    }

    // 属性个数不确定的时候， any必须是任意类型
    interface Istate3 {
        name: string|number;
        age?: number;
        [propName: string]: any;
    }

    const obj33: Istate3 = {
        name: 'Jay',
        age: 20,
        sex: "men",
        isMary: false,
        birth:'1991-01'
    }

    // 只读属性
    interface Istate4{
        name: string;
        readonly age: number;
    }

    const obj4: Istate4 = {
        name: "Jack",
        age: 55
    }
    // obj4.age = 19;

    // 6、Typescript数组类型：
    // 1) 可采用"类型[]"法表示；
    // 2) 可采用数组泛型“Array<类型>”表示法；
    // 3) 可采用接口表示法。

    let arr3: string[] = ['1','2']
    let arr4: any[] = [1,2,3,4,"5"]

    let list4:Array<string> = ['1','2']
    let list6:Array<number> = [1,23,3,4]
    let list7:Array<object> = [{},{},{}]

    interface Istate {
        name:String,
        age:Number,
        birth?:Date 
    }

    const arr9: Array<Istate> = [
        {
            name: 'Bill',
            age: 66
        },
        {
            name: "Pony",
            age: 51
        }
    ];

    // 7、Typescript函数类型：
    // 函数约束：有函数本身的参数约束，返回值约束；
    // 还有函数本身赋值的变量的约束；
    // 可采用重载的方式才支持联合类型的函数关系。

    // 申明式类型的函数
    function funType(name: string, age: number): number  {
        return age;
    }
    const ageNum: number = funType("Tom", 18);

    // 函数参数不确定
    function funType2(name: string, age: number, sex?: string): number{
        return age;
    }
    const age2Number = funType2("Tom", 18, "男");
    
        
    // 函数参数的默认值
    function funType3(name='zuo', age=18): string{
        return name;
    }

    const age3Number = funType3("zkl");

    // 表达式类型的函数
    const funType4 = function(name: string, age: number): number{
        return age;
    }

    const test = ()=>{

    }

    const funTypeMore: (name: string, age: number) => number  = function(name: string, age: number): number{
        return age;
    }
    
    // 函数接口类 
    interface IfunType6{
        (name: string, age: number): object;
    }

    const funType6: IfunType6 = function(name: string, age: number): object  {
        return {
            age,
            name 
        };
    }

    // 8、Typescript类型断言：
    // 类型断言可以用来手动指定一个值的类型。
    let abc  = true  as Boolean;

    // 9、Typescript类型别名： type

    type strType = string | number | boolean;
    type strType2 = Date | string ;
    type strType3 =  string | object | Array<any>

    // 对于接口也可以采用类型别名
    interface MuchType1{
        name: string;
    }

    interface MuchType2{
        age: number;
    }

    type MuchType = MuchType1 | MuchType2;

    // 限制字符串的选择
    type sex = "男" | "女";

    type chooseType = 1 | 2;


    // 10、Typescript枚举：
    // 枚举（enum）类型用于取值被限定在一定范围内的场景。
    // 枚举成员会被赋值为从0开始递增的数字，同时也会被枚举值到枚举名进行反向映射。

    // 使用枚举可以定义一些有名字的数字常量
    enum Days{
        Sun,
        Mon,
        Tue,
        Wed, 
        Thu, 
        Fri, 
        Sat
    }
    console.log(Days.Sun)
    console.log(Days.Sat); // 6
    console.log(Days); 
    console.log(Days[0] === "Sun"); 


    // 11、Typescript类的装饰符： class 
    // public、
    // private
    // protected。
    // public  公有变量
    // private  私有变量
    // protected 被保护的变量  

    class Comment{
        constructor(
            public id:String,
            public title:String,
            public content:String,
            public time:Date 
        ){

        }
    }

    

    interface CommentObj {
         id:String,
         title:String,
         content:String,
         time:Date 
    }

    const l1:Array<Comment> = [
        new Comment('123',"1221","2121",new Date())
    ]

    const l2:Array<CommentObj> = [{
        id:'1',
        title:"12",
        content:"123",
        time:new Date()
    }]


    // 12、Typescript泛型：
    // 泛型是指在定义函数、接口或类的时候，不预先指定具体类型，而是在使用的时候再指定类型的一种特性。T 
    // 函数中使用泛型
    function createArr<T>(length: number, value: T): Array<T>{
        const arr = [];
        for(let i = 0; i<length; i++){
            arr[i] = value;
        }

        return arr;
    }

    const strArr: number[] = createArr(8,2217);
    console.log(strArr)

    const strArr2: object[] = createArr(8,{id:2217,name:'zkl'});
    console.log(strArr2)

    // 接口当中使用泛型
    interface Icreate{
        <T>(name: string, value: T): Array<T>;
    }

    const func: Icreate = function<T>(name: string, value: T): Array<T>{
        return [];
    }

    const strArr3: number[] = func("Jack", 3);
    
    return (
        <div>
            <h2>Demo - typescript 语法的学习 </h2>
            <h2>typescript 不过是 javascript 严格的语法模式  </h2>
        </div>
    )
})

export default Demo